.TITLE XXDRV - GENERAL DEVICE INTERFACE DRIVER .IDENT /2.04/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ; BE USED AND COPIED ONLY IN ACCORDANCE WITH THE ; TERMS OF SUCH LICENSE AND WITH THE INCLUSION OF THE ; ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER ; COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE ; MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO ; AND OWNERSHIP OF THE SOFTWARE IS HEREBY ; TRANSFERRED. ; ; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR ; RELIABILITY OF ITS SOFTWARE ON EQUIPMENT THAT IS ; NOT SUPPLIED BY DIGITAL. ; ; KAREN L. NOEL AND PAUL K. M. WEISS ; ; Modified for CPRSX V2.0 by: ; ; K. L. Noel 15-May-1989 2.00 ; KLN141 - Make xxdrv return success for all QIOs before the ; remote bit has been set ; ; Paul K. M. Weiss 12-Jun-1989 2.01 ; PKW177 - Change H$TIUC and H$VUCB to H$UNIT ; ; Paul K. M. Weiss 19-Jun-1989 2.02 ; PKW181 - Buffer small QIOs and ACP QIOs in single cpr packet ; ; K. L. Noel 28-Aug-1989 2.03 ; KLN144 - Map task header at beginning of driver ; ; Modified after CPRSX V1.1 by: ; ; Paul K. M. Weiss 2-May-1990 2.04 ; PKW194 - Wouldn't it be an interesting idea to actually ; process D-space overlays? ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,PKTDF$,SCBDF$,UCBDF$,CPRDF$,TCBDF$ HWDDF$ ;DEFINE HARDWARE REGISTERS SCBDF$ ,,1 ;SCB DEFINITIONS UCBDF$ ,,1 ;UNIT CONTROL BLOCK OFFSETS PKTDF$ ;DEFINE I/O PACKET OFFSETS CPRDF$ ;CPR SPECIFIC DEFINITIONS TCBDF$ ;TCB OFFSET DEFINITIONS ; ; DEVICE DISPATCH TABLE ; DDT$ XX,1,,,,NEW=Y,,,SNX=YES ; ; LOCAL SYMBOLS ; MAP6 = 140000 ; ; IMPURE DATA ; SNDCOD:: .BLKW 1 ; FUNCTION CODE TO USE TO SEND CPR PACKET .PAGE .SBTTL XXCHK - SEND NEXT COMMAND ENTRY POINT ; ** - XXCHK - SEND NEXT COMMNAD ENTRY POINT ; ; XXCHK IS A POOR NAME, BUT THAT'S WHAT DDT$ GENERATES, SO HERE IT IS. ; THIS ROUTINE JUST SENDS THE PACKET THAT WAS ALLOCATED AT UNIT ONLINE ; TIME TO VMS. NO RETURN IS EXPECTED. ; ; XXCHK: CPSEN$ #SN$NOT,U.CPKT(R0),#H$SIZE RETURN .PAGE .SBTTL XXUCB - UNIT ONLINE ENTRY POINT ; ** - XXUCB - UNIT ONLINE ENTRY POINT ; ; FOR TT: UCBS WHICH ARE IN THE GENERIC DATA BASE, CALL THE ROUTINE ; $CPRCN TO ASSOCIATE THE TT: UCB WITH A CORRESPONDING VMS CP: UCB: ; FOR ALL OTHER UCBS, JUST RETURN ; ; SET UNIT MOUNTED (IF A MOUNTABLE DEVICE) ; ; INPUTS: ; ; R5 UCB ADDRESS ; C=1 TRANSITION TO OFFLINE ; C=0 TRANSITION TO ONLINE ; ; OUTPUTS: ; ; IE.DNR IS SET IN $SCERR IF OFFLINE TRANSITION ; XXUCB:: BCC 3$ ;IF CC ONLINE REQUEST MOVB #IE.DNR,$SCERR ;SET DEVICE NOT READY MOV U.DCB(R5),R0 ;GET THIS UNIT'S DCB CMPB #377,D.UNIT(R0) ;IS IT A GENERIC DCB BEQ 10$ ;IF EQ YES - DON'T DISCONNECT SEC ;SHOW OFFLINE CALL CALL $CPCON ;CALL CPCON TO CLEAR UCB OUT OF TABLE BR 10$ ;AND RETURN 3$: ; CHECK FOR UNIT ALREADY ONLINE SO WE DON'T DO THE CONNECT MORE THAN ONCE ; BITB #US.OFL,U.ST2(R5) ;UNIT ALREADY ONLINE? BEQ 10$ ;IF EQ YES ; ; ONLY CALL THE CONNECT ROUTINE IF THE UNIT IS A REAL UNIT, NOT A GENERIC ONE ; 5$: MOV U.DCB(R5),R0 ;GET THIS UNIT'S DCB CMPB #377,D.UNIT(R0) ;IS IT A GENERIC DCB BEQ 10$ ;IF EQ YES - DON'T CONNECT MOV #AL$NBL,R0 ;DON'T BLOCK TASK MOV #1,R1 ;ALLOCATE ONE BLOCK CALL $CPALO BCC 6$ ;IF WE GOT IT, CONTINUE MOVB #IE.IDU,$SCERR ;FAIL THE ONLINE BR 10$ ;AND RETURN 6$: MOV R0,U.CPKT(R5) ;SAVE THE PACKET IN THE UCB CALL $CPCON ;CALL THE CONNECT ROUTINE MOV @#KISAR6,-(SP) ;SAVE APR6 MAPPING MOV R0,@#KISAR6 ;MAP THE PACKET MOV #MAP6+1,R1 ;APR6 BASE ADDRESS - SKIP SIZE CLRB (R1)+ ;CLEAR SECOND BYTE MOV #H$SIZE,R2 ;SIZE OF HEADER ASR R2 ;CUT IT IN HALF DEC R2 ;FIRST WORD ALREADY DONE 7$: CLR (R1)+ ;CLEAR OUT THE HEADER SOB R2,7$ ; MOV #MAP6,R1 ;GET BASE ADDRESS BACK MOVB #HT$SNX,H$TYPE(R1) ;SEND NEXT COMMAND MOVB U.CPUN(R5),H$UNIT(R1) ;SET THE UNIT NUMBER MOV (SP)+,@#KISAR6 ;REMAP APR 6 10$: RETURN .PAGE .SBTTL XXKRB - CONTROLLER ONLINE/OFFLINE ENTRY POINT ; ** - XXKRB- CONTROLLER ONLINE/OFFLINE ENTRY POINT ; ; INPUTS: ; ; R2 KRB ADDRESS ; C=1 TRANSITION TO OFFLINE ; C=0 TRANSITION TO ONLINE ; ; OUTPUTS: ; ; IE.DNR IS SET IN $SCERR IF OFFLINE TRANSITION ; XXKRB:: BCC 10$ ;IF CC ONLINE REQUEST MOVB #IE.DNR,$SCERR ;SET DEVICE NOT READY RETURN 10$: MOV @#KISAR6,-(SP) ;SAVE APR6 MAPPING MOV $KXBAS,@#KISAR6 ;MAP THE KX DRIVER MOV @#KISAR5,MAP6+14 ;PUT THE XX BIAS IN THE KX DRIVER MOV #ALFAIL,MAP6+16 ;AND THE ALLOCATION FAILURE ENTRY POINT MOV (SP)+,@#KISAR6 ;RESTORE APR6 MAPPING RETURN $XXINT:: .PAGE .SBTTL XXINI - INITIATE I/O ENTRY POINT ; ** - XXINI - INITIATE I/O ENTRY POINT ; ; INPUTS: ; ; R1 = I/O PACKET ; R4 = SCB ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; IF RESOURCES ARE AVAILABLE, THE REQUEST IS DEQUEUED AND ; PROCESSED ACCORDING TO THE DEVICE TYPE. ; XXINI:: ; ; MAP TASK HEADER SO REFERENCES TO LUT WILL BE CORRECT ; MOV $TKTCB,R0 ;GET TCB ADDRESS MOV T.PCB(R0),R0 ;GET PCB ADDRESS MOV P.REL(R0),KISAR6 ;MAP TASK'S HEADER ; ; CHECK FOR FUNCTIONS SENT TO US FROM DREIF ; CMP #IO.CLN!1,I.FCN(R1) ;CLOSE LUN FROM DREIF? BEQ 10$ ;IF EQ YES CMP #IO.DET!1,I.FCN(R1) ;DETACH FROM DREIF? BNE 45$ ;IF NE NO 10$: CLRB I.FCN(R1) ;DON'T NEED BIT ANYMORE ; ; GET RID OF STACK CONTEXT AND SET RUNDOWN BIT ; MOV #$STACK-22,SP ;GET RID OF STACK CONTEXT MOV I.TCB(R1),R0 ;GET TCB ADDRESS MOV T.ASTL(R0),R2 ;GET ADDRESS OF FIRST AST BLOCK BEQ 40$ ;IF EQ NONE TSTB A.CBL(R2) ;KERNAL AST? BMI 50$ ;IF MI YES, RUNDOWN BIT MIGHT DEADLOCK 40$: BIS #TS.RDN,T.STAT(R0) ;SET RUN DOWN BIT BR 50$ ;NO DIRECTIVE TO FINISH 45$: ; ; FINISH DIRECTIVE - ; MOV #$STACK-24,SP ;POINT SP AT STATUS WORD ; ; (NOTE TO BENNY: THE FOLLOWING CODE WAS STOLEN FROM $DRFIN IN DRDSP) ; ; INCREMENT GROUP GLOBAL USE COUNTS (OR SCRATCH WORD IF DIRECIVES ; DON'T USE GROUP GLOBALS) ; .IF DF G$$GEF INC @$GEFPT ;INCREMENT GROUP GLOBAL USE COUNT INCB @$GFTCB ;INC GRP GLOBAL USE COUNT FOR TASK .ENDC ; DF G$$GEF ; ; WRITE DIRECTIVE STATUS BACK INTO TASK ; MTPD$ @#H.DSW ;SET DIRECTIVE STATUS WORD ; ; GET USER STACK POINTER AND UPDATE TO REMOVE DPB OR ADDRESS OF DPB FROM ; THE STACK. ; MFPI SP ;GET USER STACK POINTER ADD $BTRMV,(SP) ;REMOVE BYTES FROM USER STACK MTPI SP ;RESTORE USER STACK POINTER 50$: ; ; CALL PARAMETER CHECKING ROUTINE. THIS MUST BE CALLED BEFORE THE PACKET IS ; QUEUED SINCE THE CONTEXT MUST BE OF THE ISSUING TASK. TERMINAL QIOS HAVE A ; SEPARATE PRE-PROCESSING ROUTINE. ; MOV #XXPRE,-(SP) ;ASSUME NOT A TERMINAL QIO BIT #DV.TTY,U.CW1(R5) ;IS THIS A TERMINAL DEVICE? BEQ 60$ ;IF EQ NO, USE XXPRE MOV #XXTTI,(SP) ;USE XXTTI INSTEAD 60$: CALL @(SP)+ ;DO PACKET PREPROCESSING BCC TSTQUE ;GO DEQUEUE A PACKET JMP IOFIN ;IF CS ERROR - STATUS IN R0,R1 ; ; TSTQUE IS ONLY BRANCHED TO WHEN WE KNOW WE HAVE AT LEAST ONE PACKET IN THE ; QUEUE. IF THERE IS MORE THAN ONE, IT MEANS THAT A PREVIOUS ONE MUST HAVE ; FAILED TO ALLOCATE A CPR PACKET. IN THAT CASE, JUST RETURN, WE'LL TRY TO ; SEND IT WHEN KXDRV CALLS BACK ; TSTQUE: TST @(R4) ;MORE THAN ONE ENTRY IN QUEUE? BEQ ALPKT ;IF EQ NO RETURN ;ALREADY WAITING FOR BUFFER ; ; ALLOCATE A CPRBUF REQUEST PACKET ; ; WE DO NOT DO IMPLICIT TASK START! ; THE TASK HAS ALREADY BOUND THE LUN WITH ITS AME. THIS MEANS THAT THE ; IMPLICIT TASK START HAD TO HAVE ALREADY HAPPENED. SINCE WE MAY NOT BE RUNNING ; UNDER THE CONTEXT OF THE SAME TASK THAT ISSUED THE QIO, THE VALUE IN $TKTCB IS ; NOT VALID. THE KXDRIVER USES $TKTCB TO SEE IF IT NEEDS TO DO AN IMPLICIT TASK ; START ONLY IF THE AL$IMP BIT IS SET. ; ; THE KXDRIVER WILL NOT RETURN FROM THE CPALO CALL IF IT FAILS TO ALLOCATE A ; BLOCK OF CPRBUF. SINCE WE DO NOT NECESSARILY HAVE THE TASK CONTEXT AND WE DO ; NOT WANT TO REISSUE THE QIO, WHEN RESOURCES BECOME AVAILABLE, THE KXDRIVER ; WILL CALL US BACK AT ALFAIL (SET UP BY XXKRB) TO REISSUE THE REQUEST. ; ; ; IF THE HIGH BIT OF I.LN2 IS SET, I.PRM CONTAINS A PRE-ALLOCATED CPR PACKET ALFAIL: MOV U.SCB(R5),R4 ;RESTORE THE SCB ALPKT: MOV (R4),R0 ;GET AN I/O PACKET BEQ 20$ ;SHOULDN'T BE NONE, BUT JUST IN CASE TST I.LN2(R0) ;IS A CPR PACKET PREALLOCATED? BPL 10$ ;NOPE, ALLOCATE ONE MOV I.PRM(R0),-(SP) ;USE THE PREALLOCATED PACKET BR 31$ ;CONTINUE IN COMMON 10$: CLR R0 ;ASSUME NO CPR PACKET BIT #HF.RMT,$HFMSK ;ARE WE A REMOTE SYSTEM, YET? BEQ 30$ ;IF NOT, DON'T GET A PACKET MOV #AL$XXD,R0 ;INDICATE NO BLOCKING AND NO PC BACKUP MOV #1,R1 ;ALLOCATE 1 BLOCK CALL $CPALO ;CALL ALLOCATE ROUTINE IN KXDRV ; ; GET AN I/O PACKET FROM THE QUEUE ; WE USE $GSPKT INSTEAD OF $GTPKT SINCE WE IGNORE THE BUSY BIT IN THE ; CONTROLLER. THE AME WILL DECIDE IF A PARTICULAR CONTROLLER IS TOO BUSY. ; SINCE WE ACCEPT ANY PACKET, WE WILL ALWAYS GET THE FIRST PACKET IN THE QUEUE ; 30$: MOV R0,-(SP) ;SAVE BUFFER BIAS 31$: MOV #20$,R2 ;ADDRESS OF ACCEPTANCE ROUTINE CALL $GSPKT ;DEQUEUE I/O PACKET MOV (SP)+,R0 ;RESTORE BUFFER BIAS BCC 40$ ;IF CC, WE GOT AN I/O PACKET ; ; THIS SHOULD NEVER HAPPEN. $GSPKT IS SPECIAL CASED TO GIVE US ANY PACKET ; IN OUR QUEUE INCLUDING ATTACH AND DETACH. THIS IS HERE TO PROTECT OURSELVES ; AND THE AME ; BEQ 20$ ;IF ZERO, DON'T HAVE A PACKET CALLR $CPDEA ;DEALLOCATE THE CPRBUF PACKET AND RETURN ; ; THIS IS THE DRIVER ACCEPTANCE ROUTINE FOR $GSPKT - WE ACCEPT ANYTHING 20$: CLC ;CLEAR CARRY FOR GSPKT$ CALL RETURN ; ; ; AFTER CALL TO $GSPKT ; ; R0 = CPR PACKET BIAS ; R1 = ADDRESS OF I/O PACKET ; R2 = PHYSICAL UNIT # ; R3 = CONTROLLER INDEX ; R4 = SCB ADDRESS ; 40$: BIT #HF.RMT,$HFMSK ;ARE WE A REMOTE SYSTEM, YET? BNE 42$ ;IF SO, KEEP GOING ; ; WE ARE NOT A REMOTE SYSTEM YET, JUST RETURN SUCCESS ; MOV I.TCB(R1),R5 ; GET TCB ADDRESS BIC #TS.RSW,T.STAT(R5) ; CLEAR BLOCKING BIT MOV R1,R5 ; GET I/O PACKET ADDRESS MOV #1,-(SP) ; PUSH STATUS WORDS MOV #0,-(SP) ; CLR R0 ; SHOW NO CPR PACKET TST I.LN2(R1) ; PACKET ALREADY ALLOCATED? BPL 41$ ; NOPE, NO PACKET MOV I.PRM(R1),R0 ; GET THE PREALLOCTED PACKET 41$: JMP CMPLIO ; COMPLETE I/O 42$: ; ; WE HAVE A PACKET. SET THE DEFAULT CODE TO BE USED TO SEND IT. ; MOV #SN$QIO,SNDCOD ; DEFAULT IS A NORMAL QIO. ; ; CHECK FOR OVERLAY QIO'S ; MOV I.UCB(R1),R5 ;GET UCB ADRESS TST U.CW1(R5) ;MOUNTABLE DEVICE? BPL 50$ ;IF PL NO, CAN'T BE OVERLAY FUNCTION MOV I.FCN(R1),R2 ;GET FUNCTION CODE CMP #IO.LOV,R2 ;IS IT THE I-SPACE LOAD OVERLAY? BEQ 45$ ;IF EQ YES CMP #IO.LDO,R2 ;IS IT THE D-SPACE LOAD OVERLAY? BNE 50$ ;IF NE NO 45$: JMP OVERLD ; 50$: ; ; CHECK FOR ATTACH OR NETWORK SPECIFY AST QIO. ; MOV (R5),R3 ;GET DCB CMPB I.FCN+1(R1),#IO.ATT/256. ;ATTACH? BEQ 55$ ;IF EQ YES CMP D.NAM(R3),#"NS ;IS THIS THE NETWORK? BNE 57$ ;IF NE NO CMP I.FCN(R1),#16420 ;NETWORK SPA? BNE 57$ ;IF NE NO TST I.PRM(R1) ;IS AN AST ADDRESS SPECIFIED BEQ 57$ ;NO, IT'S DELETING THE REQUEST. 55$: MOV R0,-(SP) ;SAVE R0 MOV R1,-(SP) ; AND R1 MOV R4,-(SP) ; AND R4 CALL XXATT ;DO ATTACH (CARRY SET IF ERROR DETECTED) MOV R0,R2 ;SAVE ERROR CODE, IF ANY. MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R1 ; AND R1 MOV (SP)+,R0 ; AND R0 BCC 57$ ;CONTINUE NORMALLY IF NO ERROR. MOV R2,-(SP) ;PRESERVE ERROR CODE. MOV R1,-(SP) ;PRESERVE I/O PACKET ADDRESS. CALL $CPDEA ;RELEASE CPR PACKET. MOV (SP)+,R1 ;RESTORE I/O PACKET ADDRESS. MOV (SP)+,R0 ;RESTORE ERROR CODE. MOV I.TCB(R1),R3 ;GET TCB. BIC #TS.RSW,T.STAT(R3) ;THERE IS NO WAIT FOR THIS ERROR. MOV R1,R3 ;IOFIN WANTS I/O PACKET IN R3. CLR R1 ;CLEAR TOP HALF OF ERROR CODE. JMP IOFIN ;COMPLETE THIS I/O WITH ERROR STATUS. 57$: BIT #DV.TTY,U.CW1(R5) ;IS THIS A TERMINAL DEVICE? BEQ 575$ ;NO, FORGET ABOUT SF.GMC. CMP #IO.GTS,I.FCN(R1) ;IS THIS GET SUPPORT REQUEST? BEQ 573$ ;YES, WE BLOCK THOSE. CMP #SF.GMC,I.FCN(R1) ;HOW ABOUT GET CHARACTERISTICS? BNE 575$ ;NOPE, LET IT GO NORMALLY. 573$: BIS #SF$BLK,SNDCOD ;INDICATE TASK IS BLOCKED FOR THIS ; OPERATION. 575$: ; ; START FILLING IN THE CPRBUF REQUEST PACKET ; ; THE FOLLOWING PARAMETERS ARE INSERTED AFTER THE PACKET HEADER: ; ; | | | ; +---------------+---------------+ ; | BUFFER FLAGS | LUN NUMBER | P$LUN ; +---------------+---------------+ ; | RESERVED | P$LUN+2 ; +---------------+---------------+ ; | I.FCN | P$LUN+4 ; +---------------+---------------+ ; | I.PRM | P$LUN+6 ; +---------------+---------------+ ; | I.PRM+2 | P$LUN+10 ; +---------------+---------------+ ; | I.PRM+4 | P$LUN+12 ; +---------------+---------------+ ; | I.PRM+6 | P$LUN+14 ; +---------------+---------------+ ; | I.PRM+10 | P$LUN+16 ; +---------------+---------------+ ; | I.PRM+12 | P$LUN+20 ; +---------------+---------------+ ; | I.PRM+14 | P$LUN+22 ; +---------------+---------------+ ; | I.PRM+16 | P$LUN+24 ; +---------------+---------------+ ; | SCB | P$LUN+26 ; +---------------+---------------+ ; | I/O PACKET | P$LUN+30 ; +---------------+---------------+ ; | USER BUFFER BIAS-SMALL READS | P$LUN+32 ; +---------------+---------------+ ; | USER BUFFER OFFSET-SMALL READS| P$LUN+34 ; +---------------+---------------+ ; ; THE FLAGS BYTE IS A BITMAP FOR I/O BUFFERS. EACH BIT SET CORRESPONDS TO THE ; BEGINNING OF A BIAS/OFFSET/LENGTH TRIPLET IN THE 8-WORD I.PRM AREA. IF THE ; HIGH BIT IS SET, THEN I.PRM CONTAINS A PREALLOCATED CPR PACKET ; MOV R0,@#KISAR6 ;MAP THE PACKET MOV #MAP6,R2 ;POINT TO THE HEADER MOVB #HT$QIO,H$TYPE(R2) ;ASSUME REGULAR QIO REQUEST CLRB H$ICNT(R2) ;NO ITEMS ADD #P$LUN,R2 ;POINT TO THE PARAMETER AREA ; ; FINISH FILLING IN THE I/O PACKET, WE ASSUME THERE CAN NOT BE MORE THAN 8 ; PARAMETER WORDS 60$: MOV I.LN2(R1),(R2)+ ;FILL IN P$LUN FIELD AND FLAGS WORD TST (R2)+ ;RESERVED WORD MOV I.FCN(R1),(R2)+ ;FILL IN I/O FUNCTION CODE MOV R1,R3 ADD #I.PRM,R1 ;POINT TO THE PARAMTER LIST .REPT 8. MOV (R1)+,(R2)+ ;COPY PARAMETERS .ENDR MOV R4,(R2)+ ;COPY SCB ADDRESS INTO PACKET MOV R3,(R2)+ ;COPY I/O PACKET ADDRESS CMP (R2)+,(R2)+ ;SKIP PAST USER BIAS/OFFSET MOV R3,R1 ;RESTORE PKT TO R1 TST I.LN2(R1) ;IS THE PACKET PREALLOCATED? BPL SENPKT ;NOPE, LEAVE NOW CMPB #IO.RLB/256.,I.FCN+1(R3) ;IS THIS READ LOGICAL BLOCK? BEQ SENPKT ;YES, DON'T COPY THE EMPTY BUFFER CMPB #IO.RVB/256.,I.FCN+1(R3);HOW ABOUT READ VIRTUAL BLOCK? BEQ SENPKT ;SAME, DON'T COPY EMPTY BUFFER MOVB MAP6,R2 ;GET SIZE IN BLOCKS - SEND WHOLE THING ASH #6,R2 ;MAKE INTO BYTE OFFSET ADD #MAP6,R2 ;ADD BASE OFFSET ; ; SEND QIO REQUEST TO AME ; SENPKT: MOV R5,-(SP) ;SAVE THE UCB MOV I.TCB(R1),R5 ;GET THE TCB - MAY NOT BE CURRENT TASK SUB #MAP6,R2 ;GET SIZE OF REQUEST CPSEN$ SNDCOD,R0,R2,#SNDRET ; ; GET RETURN PACKET ; MOV R0,@#KISAR6 ;MAP PACKET MOV #MAP6,R2 ;POINT TO HEADER OF PACKET MOV P$PARM+22(R2),R1 ;GET I/O PACKET ADDRESS MOV I.UCB(R1),R5 ;GET UCB ADDRESS MOV (R5),R3 ;GET DCB CMPB #IO.ATT/256.,I.FCN+1(R1) ;IS THIS AN ATTACH REQUEST? BEQ 7$ ;YES, CHECK IT OUT. CMPB I.FCN+1(R1),#IO.DET/256. ;DETACH? BEQ 8$ ;YES, DO DETACH. CMP D.NAM(R3),#"NS ;IS THIS THE NETWORK? BNE 10$ ;NO, SKIP DETACH. CMP I.FCN(R1),#16410 ;IS THIS A NETWORK CLOSE? BEQ 8$ ;YES, CANCEL THE AST. CMP I.FCN(R1),#IO.CLN*400 ;IS THIS A NETWORK CLOSE LUN? BEQ 8$ ;YES, CANCEL THE AST. CMP I.FCN(R1),#16420 ;NETWORK SPA? BNE 10$ ;NO, SKIP DETACH. TST I.PRM(R1) ;IS AN AST ADDRESS SPECIFIED BEQ 8$ ;NO, EMULATE DETACH. ;YES, CHECK FOR SUCCESS. 7$: CMP H$STAT(R2),#1 ;DID ATTACH SUCCEED BEQ 10$ ;IF EQ YES 8$: MOV I.UCB(R1),R5 ;GET UCB ADDRESS OF UNIT ; ; DEALLOCATE ACB ; MOV R0,-(SP) ;SAVE R0 MOV R2,-(SP) ;AND R2 CALL XXDET ;DEQUEUE AND DEALLOCATE ACB MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R0 ;AND R0 10$: MOV P$PARM+20(R2),R4 ;SAVE SCB ADDRESS MOV P$PARM+22(R2),R5 ;SAVE I/O PACKET ADDRESS MOV H$STAT(R2),-(SP) ;GET FIRST STATUS WORD MOV H$STAT+2(R2),-(SP) ;AND SECOND STATUS WORD ; ; CONVERT LUN NUMBER BACK INTO POINTER INTO LUT ; CMPLIO: MOVB I.LN2(R5),R3 ;GET LUN NUMBER DEC R3 ;LUN NUMBERS START AT 1 ASL R3 ;MULTIPLY BY 4 (4 BYTES PER LUN ENTRY) ASL R3 ; ADD #,R3 ;GET OFFSET INTO LUT MOV R3,I.LN2(R5) ;RETURN TO LUN FIELD IN I/O PACKET ; ; COMPLETE I/O ; MOV R5,R3 ;GET I/O PACKET ADDRESS MOV I.UCB(R3),R5 ;GET UCB ADDRESS ; XXFIN USES THE FIRST I/O STATUS WORD, AT 4(SP), INCLUDING RETURN ADDRESS ; WE ARE ABOUT TO GENERATE. CALL XXFIN ;DO FINISH WORK FOR NON TERMINAL DEVICES ;XXFIN: PRESERVES R4,R5 AND STACK MOV (SP)+,R1 ;SETUP STATUS WORDS FOR $IODSA MOV (SP)+,R0 ; ; ; COMMON POINT TO ALL I/O TO FINISH - SUCCESS OR ERROR ; ; R0,R1 - STATUS ; R3 - I/O PACKET ; R5 - UCB ADDRESS ; IOFIN: CLR I.PRM+16(R3) ;MAKE IOFIN KNOW WE DON'T HAVE A BLOCK ;LOCKING ; $IODSA WILL FORK USING THE I/O PACKET AS THE FORK BLOCK IF THERE IS ; ANOTHER I/O PACKETS IN OUR QUEUE. ; THIS WILL ENSURE THAT THE KX DRIVER WILL GET TO COMPLETE ITS ; RING PROCESSING AS SOON AS POSSIBLE. ; CALL $IODSA ;CALL I/O COMPLETION ROUTINE ; ; SEE IF ANYTHING ELSE IS IN OUR QUEUE ; NEMORE: MOV U.SCB(R5),R4 ;RESTORE SCB ADDRESS TST (R4) ;ANOTHER PACKET IN QUEUE? BNE 10$ ;YES, CHECK IT OUT RETURN 10$: JMP ALPKT SNDRET: MOV (SP)+,R5 ;RESTORE THE UCB ADDRESS BR NEMORE ;SEE IF THERE ARE ANY MORE TO SEND ;+ ; ; OVERLD - HANDLE LOAD OVERLAY REQUESTS TO CPRSYS ; ; INPUT: R0 - BIAS OF THE REQUEST PACKET ; R1 - ADDRESS OF I/O PACKET ; ;- OVERLD: ; ; FILL IN THE CPRBUF REQUEST PACKET ; MOV R0,@#KISAR6 ;MAP THE PACKET MOV #MAP6,R2 ;POINT TO THE HEADER MOVB #HT$LOV,H$TYPE(R2) ;LOAD OVERLAY REQUEST CLRB H$ICNT(R2) ;NO ITEMS MOV R4,P$PARM+20(R2) ;SAVE THE SCB ADDRESS MOV R1,P$PARM+22(R2) ;SAVE THE I/O PACKET ADDRESS ADD #P$IID,R2 ;POINT TO THE PARAMETER AREA ; ; LOAD PARAMETERS ; MOV I.TCB(R1),R4 ;GET TCB ADDRESS OF REQUESTING TASK MOV T.IID(R4),(R2)+ ;FILL IN IMAGE INDEX FIELD MOV I.PRM+4(R1),(R2)+ ;FILL IN SIZE MOV I.PRM(R1),(R2)+ ;FILL IN BIAS MOV I.PRM+2(R1),(R2)+ ;FILL IN DISPLACEMENT MOV I.PRM+12(R1),(R2)+ ;FILL IN BLOCK NUMBER ; ; SEND QIO REQUEST TO CPRSYS ; JMP SENPKT ;AND GO SEND THE PACKET TO VMS XXOUT:: XXPWF:: RETURN .PAGE .SBTTL XXCAN- CANCEL I/O ENTRY POINT ; ** - XXCAN- CANCEL I/O ENTRY POINT ; ; CANCEL I/O FOR ALL OUTSTANDING I/O ON THE UNIT SPECIFIED BY THE UCB IN R5 ; ; FIRST SCAN THE DRIVER'S QUEUE FOR I/O PACKETS WHICH HAVEN'T BEEN SHIPPED ; OVER YET. ONLY THOSE I/O PACKETS WHOSE TCB ADDRESSES MATCH THAT OF THE ; CURRENT TASK AND WHOSE UCB ADDRESSES MATCH WILL BE CONCIDERED. SINCE THE ; UCB ADDRESS DOES NOT IDENTIFY A UNIQUE UNIT, THE LUN NUMBER IS CHECKED ; AGAINST THE ONE PASSED TO US. IF ALL THESE MATCH, THE PACKET IS REMOVED ; FROM THE QUEUE AND THE I/O FINISHED. IF THE UCB ADDRESSES MATCH AND LUN ; NUMBERS DON'T, WE MUST DO A FAKE GDVI DIRECTIVE TO FIND OUT IF THE UNITS ; ARE THE SAME. ; ; INPUTS: ; ; R1 TCB ADDRESS OF CURRENT TASK ; R4 SCB ADDRESS OF XX SCB ; R5 UCB ADDRES TO KILL I/O TO ; $CPPKT BIAS OF A PACKET IN CPRBUF TO USE FOR I/O KILL OR GDVI REQUEST ; $CPLUN LUN NUMBER OF I/O KILL REQUEST ; P$LUN+2 OFF CPRBUF PACKET CONTAINS THE NUMBER OF WORDS ON THE STACK ; WHICH MUST BE SAVED IF A GDVI PACKET MUST BE PASSED ; $TEMP2 ; ; OUTPUTS: ; ; APPROPRIATE I/O PACKETS ARE REMOVED FROM THE QUEUE AND AN I/O KILL ; PACKET IS SENT TO THE HOST, TO KILL ALL I/O OUTSTANDING ON THE LUN ; XXCAN:: ; ; SCAN SCB QUEUE FOR PACKETS TO KILL ; MOV R4,R3 ;COPY ADDRESS OF I/O QUEUE LISTHEAD 10$: MOV R3,R2 ;SAVE ADDRESS OF CURRENT ENTRY MOV (R2),R3 ;GET ADDRESS OF NEXT ENTRY BEQ 100$ ;IF EQ, NONE ; ; FOUND AN ENTRY IN THE SCB QUEUE ; ; - THIS IS A VERY STRANGE CASE SINCE THE GENERIC DRIVER ONLY HOLDS ONTO I/Os ; IF RESOURCES ARE LACKING ; - TO HANDLE THIS SITUATION, WE WILL MAKE ONLY 2 CHECKS. IF THE I/O HAS COME ; FROM THIS TASK AND IF THE LUN NUMBERS ARE THE SAME. THE OTHER SITUATIONS ; WHICH SHOULD BE HANDLED, I/O FROM THIS TASK WITH DIFFERENT LUN NUMBERS AND ; THE SAME UCB ADDRESS CAN'T BE HANDLE WITHOUT MUCH PAIN BECAUSE OF THE ; GENERIC UCB STRUCTURE. THIS IS NOT A TERRIBLE RESTRICTION. IF ; RESOURCES ARE LACKING, THIS CANNOT BE AN IO.KIL QIO SINCE DRQIO DOES NOT ; LET THE QIO COME THROUGH UNLESS A CPRBUF PACKET IS AVAILABLE. IF WE ARE ; BEING CALLED BECAUSE OF AN ALUN OR PFCS DIRECTIVE, SOMETHING IS REALLY ; STRANGE BECAUSE THE DIRECTIVE MADE IT TO CPRAME BUT THE I/O PACKET ; COULDN'T. ; CMP R1,I.TCB(R3) ;REQUEST FOR CURRENT TASK? BNE 10$ ;IF NE NO TST $CPLUN ;IS KILL FOR ALL UNITS? (FROM DREIF) BEQ 50$ ;IF EQ YES MOV I.LN2(R3),R0 ;GET POINTER TO SECOND LUN WORD SUB #H.LUN+2+MAP6,R0 ;CALCULATE LUN NUMBER ASR R0 ;DIVIDE BY 4 ASR R0 ; CMP R0,$CPLUN ;IS IT THE SAME LUN? BNE 10$ ;IF NE NO - DON'T KILL IT ; ; REMOVE I/O PACKET FROM QUEUE ; 50$: MOV (R3),(R2) ;CLOSE UP LIST BNE 60$ ;IF NE NO NEW LAST MOV R2,2(R4) ;SET ADDRESS OF NEW LAST ; ; COMPLETE I/O WITH ABORT STATUS ; 60$: MOV #IE.ABO&377,R0 ;SET FINAL STATUS TO ABORT TSTB $TEMP2 ;SUBFUNCTION SET FOR IO.KIL? BMI 70$ ;IF MI YES CLR I.AST(R3) ;MAKE SURE THERE IS NO AST DECLARED 70$: CLR R1 ;CLEAR SECOND STATUS WORD CALL $IOFIN ;FINISH I/O REQUEST ; ; GO BACK TO SCAN SCB LIST FOR MORE I/O PACKETS ; MOV U.SCB(R5),R4 ;GET SCB ADDRESS BACK MOV $TKTCB,R1 ;GET CURRENT TASK TCB ADDRESS BACK JMP XXCAN ;SCAN QUEUE AGAIN ; ; PUT PACKET TOGETHER TO KILL I/O ; 100$: MOV $CPPKT,@#KISAR6 ;MAP THE PACKET BEQ 200$ ;IF EQ DON'T KILL I/O MOV #MAP6,R2 ;POINT TO THE HEADER MOVB #HT$QIO,H$TYPE(R2) ;QIO REQUEST CLRB H$ICNT(R2) ;NO ITEMS MOVB $CPLUN,P$LUN(R2) ;FILL IN LUN CLRB P$FLG(R2) ;NO BUFFERS MOV #IO.KIL,P$FUNC(R2) ;FILL IN FUNCTION CODE ; ; SEND QIO REQUEST TO AME WITH IMMEDIATE RETURN - PACKET WILL BE DEALLOCATE ; ON DETATCHED RETURN BY KXDRV ; MOV R1,R5 ;SET UP TCB FOR PSEUDO REQUEST CPSEN$ #SN$PSR,KISAR6,#H$SIZE+6 CLR $CPPKT ;INDICATE THAT I/O HAS BEEN KILLED 200$: RETURN .END